package hydrap2p.proxy.manager;

import java.util.LinkedList;
import java.util.List;

import hydrap2p.helper.ServiceConnector;
import hydrap2p.logging.Level;
import hydrap2p.logging.Logging;

import org.apache.thrift.TException;

public class ProxyLogging {

	private static long lastCheck=0;
	private static final int checkOften=10000; 
	private static DeferredLogging logger = new DeferredLogging();
	public static void log(Level level, String source, String reason)
	{
		logger.log(level, source, reason);
	}	
	
	private static class DeferredLogging
	{

		private class LogEntry
		{
			public Level level;
			public String source;
			public String reason;
			public LogEntry(Level level, String source, String reason) {
				this.level = level;
				this.source = source;
				this.reason = reason;
			}
		}
		
		private final List<LogEntry> queue;
		private boolean running;
		private DeferredLogPusher pusher;

		public DeferredLogging() {
			queue = new LinkedList<LogEntry>();
			running=true;
			pusher=new DeferredLogPusher();
			new Thread(pusher, "Deferred Logging").start();			
		}
		
		public void log(Level level, String source, String reason)
		{
			LogEntry entry = new LogEntry(level, source, reason);
			synchronized(queue)
			{
				//System.err.println("Adding new log entry: "+reason);
				queue.add(entry);
				queue.notify();
			}
		}
		
		private class DeferredLogPusher implements Runnable {

			private Logging.Iface logger;
			
			@Override
			public void run() {
				while (running)
				{
					LogEntry entry=null;
					synchronized(queue)
					{
						if (queue.size()>0)
							entry=queue.remove(0);
					}
					if (entry!=null)
					{
						if (logger==null && System.currentTimeMillis()>(lastCheck+checkOften))
						{
							logger=ServiceConnector.getLogger();
							lastCheck=System.currentTimeMillis();
						}
						if (logger==null)
						{
							int deep=Thread.currentThread().getStackTrace().length;
							for (int x=0; x<deep; x++) System.err.print(" ");
							System.err.println(entry.source+": "+entry.reason);
						}
						else
						{
							try {
								logger.log(entry.level, entry.source, entry.reason);
							} catch (TException e) {
								System.err.println(entry.source+": "+entry.reason);
								logger=null;
							}
						}
					}
					else
					{
						synchronized(queue) {
							try {
								queue.wait();
							} catch (InterruptedException e) {
								// We might be done
							}
						}
					}
				}
			}
			
		}
		
	}
}
